package wiki.laona.service.impl;

import io.minio.*;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import wiki.laona.constant.EnumFileType;
import wiki.laona.constant.MinioConstant;
import wiki.laona.service.IMinioService;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @author laona
 * @decription minio 服务实现
 * @since 2022-06-29 21:23
 **/
@Slf4j
@Service
public class MinioServiceImpl implements IMinioService {

    @Resource
    private MinioClient minioClient;

    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    @Override
    public String upload(String fileName, InputStream stream, EnumFileType fileType) throws Exception {

        String result;
        if (ObjectUtils.nullSafeEquals(fileType, EnumFileType.IMAGE.type)) {

            checkAndMakeBucket(MinioConstant.IMAGES_BUCKET_NAME);

            PutObjectArgs args = new PutObjectArgs.Builder()
                    .bucket(MinioConstant.IMAGES_BUCKET_NAME)
                    .stream(stream, stream.available(), -1)
                    .object(fileName)
                    .build();
            ObjectWriteResponse writeResponse = minioClient.putObject(args);
            log.info("response: {}", writeResponse);
            result = MinioConstant.IMAGES_BUCKET_NAME + "/" + fileName;
        } else {

            checkAndMakeBucket(MinioConstant.DEFAULT_BUCKET_NAME);

            PutObjectArgs args = new PutObjectArgs.Builder()
                    .bucket(MinioConstant.DEFAULT_BUCKET_NAME)
                    .object(fileName)
                    .stream(stream, stream.available(), -1)
                    .build();
            ObjectWriteResponse writeResponse = minioClient.putObject(args);
            log.info("response: {}", writeResponse);
            result = MinioConstant.DEFAULT_BUCKET_NAME + "/" + fileName;
        }

        return result;
    }

    /**
     * 检查并创建不存在的bucket
     *
     * @param bucketName bucket name
     * @throws ServerException           exception
     * @throws InsufficientDataException exception
     * @throws ErrorResponseException    exception
     * @throws IOException               exception
     * @throws NoSuchAlgorithmException  exception
     * @throws InvalidKeyException       exception
     * @throws InvalidResponseException  exception
     * @throws XmlParserException        exception
     * @throws InternalException         exception
     */
    private void checkAndMakeBucket(String bucketName) throws ServerException,
            InsufficientDataException,
            ErrorResponseException,
            IOException,
            NoSuchAlgorithmException,
            InvalidKeyException,
            InvalidResponseException,
            XmlParserException,
            InternalException {

        if (!StringUtils.hasText(bucketName)) {
            throw new IllegalArgumentException("bucket name must not empty!");
        }

        BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder()
                .bucket(bucketName)
                .build();

        if (!minioClient.bucketExists(bucketExistsArgs)) {

            MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build();
            minioClient.makeBucket(makeBucketArgs);
        }
    }
}
